﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.Publishing;
namespace SPHelper
{
	public class WebPart
	{
		/// <summary>
		/// Get web parts manager from passed url
		/// </summary>
		/// <param name="web"></param>
		/// <param name="pageUrl"></param>
		/// <returns></returns>
		public static SPLimitedWebPartManager GetWebPartManager(string pageUrl)
		{
			SPLimitedWebPartManager webPartManager = null;
			try
			{
				// init
				if (pageUrl == null) { throw new Exception("PublishingPage passed is null"); }
				SPWeb web = SPHelper.Web.GetWeb();
				if (web == null) { throw new Exception("Failed to get SPWeb from passed url"); }
				if (!SPHelper.Validation.IsValidUrl(pageUrl)) { throw new Exception("Invalid page url passed"); }


				webPartManager = web.GetLimitedWebPartManager(pageUrl, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
			}
			catch (Exception ex)
			{
				Log.WriteError("srdgdfyjdGGtysrd", ex, "url: " + pageUrl);
				webPartManager = null;
			}
			return webPartManager;
		}

		/// <summary>
		/// Get Web Part Manager from wiki or publishing page's SPFile object
		/// </summary>
		/// <param name="file"></param>
		/// <returns></returns>
		public static SPLimitedWebPartManager GetWebPartManager(SPFile file)
		{
			SPLimitedWebPartManager webPartManager = null;
			try
			{
				// init
				if (file == null) { throw new Exception("SPFile passed is null"); }
				webPartManager = file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
			}
			catch (Exception ex)
			{
				string pageUrl = null; if (file != null) { pageUrl = file.Url; }
				Log.WriteError("trydtrgfdfsdrtrdts", ex, "url: " + pageUrl);
				webPartManager = null;
			}
			return webPartManager;
		}

		/// <summary>
		/// get web part manager from passed publishing page
		/// </summary>
		/// <param name="page"></param>
		/// <returns></returns>
		public static SPLimitedWebPartManager GetWebPartManager(PublishingPage page)
		{
			SPLimitedWebPartManager webPartManager = null;
			try
			{
				// init
				if (page == null) { throw new Exception("PublishingPage passed is null"); }

				// call original
				webPartManager = GetWebPartManager(page.ListItem.File);
			}
			catch (Exception ex)
			{
				string pageUrl = null; if (page != null) { pageUrl = page.Url; }
				Log.WriteError("srdgdfyjdGGtysrd", ex, "url: " + pageUrl);
				webPartManager = null;
			}
			return webPartManager;
		}

		/// <summary>
		/// Get GetLimitedWebPartManager for webPart page, such as wiki page
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		public static SPLimitedWebPartManager GetWebPartManager(SPListItem item)
		{
			SPLimitedWebPartManager webPartManager = null;
			try
			{
				// init
				if (item == null) { throw new Exception("SPListItem passed is null"); }
				if (item.File == null) { throw new Exception("item.File is null"); }

				// call original
				webPartManager = GetWebPartManager(item.File);
			}
			catch (Exception ex)
			{
				string itemUrl = null; if (item != null) { itemUrl = item.Url; }
				Log.WriteError("strydjrdthrsersetrrs", ex, "url: " + itemUrl);
				webPartManager = null;
			}
			return webPartManager;
		}

		

		public enum WebPartScope
		{
			Web,
			Site,
			WebApplication,
			Farm,
		}
		/// <summary>
		/// Get webpart url
		/// This is a link to the webpart that is used for adding it to a page
		/// </summary>
		/// <param name="web"></param>
		/// <param name="webPartFilename"></param>
		/// <param name="scope"></param>
		/// <returns></returns>
		public static string GetWebPartUrl(SPWeb web, string webPartFilename, WebPartScope scope)
		{
			string url = null;
			try
			{
				// init
				if (web == null) { web = Web.GetWeb(); }
				if (web == null) { throw new Exception("SPWeb passed is null and failed to get it from SPContext"); }
				if (string.IsNullOrEmpty(webPartFilename)) { throw new Exception("WebPart filename passed is null"); }


				if (scope == WebPartScope.Web)
				{
					url = web.Url + "/_catalogs/wp/" + webPartFilename;
				}
				else if (scope == WebPartScope.Site)
				{
					url = web.Site.RootWeb.Url + "/_catalogs/wp/" + webPartFilename;
				}
				else
				{
					throw new Exception("Don't know how to get url for webpart in scope: " + scope.ToString());
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("sdtfguidstrsrdsdr", ex);
			}
			return url;
		}


		/// <summary>
		/// Get webpart
		/// </summary>
		/// <param name="web"></param>
		/// <param name="pageUrl"></param>
		/// <param name="webPartUrl"></param>
		/// <returns></returns>
		public static System.Web.UI.WebControls.WebParts.WebPart GetWebPart(SPLimitedWebPartManager webPartManager, 
			string webPartFilename, WebPartScope scope)
		{
			System.Web.UI.WebControls.WebParts.WebPart webpart = null;
			try
			{
				// init
				if (webPartManager == null) { throw new Exception("webPartManager passed is null"); }
				if (string.IsNullOrEmpty(webPartFilename)) { throw new Exception("Web Part Filename passed is null"); }


				// get webPartUrl
				string webPartUrl = GetWebPartUrl(webPartManager.Web, webPartFilename, scope);
				if (string.IsNullOrEmpty(webPartUrl)) { throw new Exception("Failed to get webPart url using filename: " + webPartFilename + " and scope: " + scope); }

				// get xml reader of webpart
				System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(
				    new System.IO.StringReader(webPartManager.Web.GetFileAsString(webPartUrl)));
				if (reader == null || reader.IsEmptyElement) { throw new Exception("Failed to get webpart using url: " + webPartUrl); }

				// get webpart object
				string errorMessage = null;
				webpart = webPartManager.ImportWebPart(reader, out errorMessage);
				if (webpart == null || !string.IsNullOrEmpty(errorMessage))
				{
				    throw new Exception("Failed to reference webpart using url: " + webPartUrl + " with error: "
				    + errorMessage);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("7iurewtJJrtyfddsfsdhf", ex, "webPart filename: " + webPartFilename);
				webpart = null;
			}
			return webpart;
		}


		///// <summary>
		///// Add a webpart to a page
		///// </summary>
		///// <param name="web"></param>
		///// <param name="pageUrl"></param>
		///// <param name="webPartUrl"></param>
		///// <param name="zoneId"></param>
		//public static System.Web.UI.WebControls.WebParts.WebPart AddWebPart(PublishingPage page, System.Web.UI.WebControls.WebParts.WebPart, string zoneId)
		//{
		//    System.Web.UI.WebControls.WebParts.WebPart webPart = null;
		//    try
		//    {
		//        // init
		//        if (web == null) { web = Web.GetWeb(); }
		//        if (web == null) { throw new Exception("SPWeb passed is null and failed to get it from SPContext"); }
		//        if (string.IsNullOrEmpty(pageUrl)) { throw new Exception("Url for webpart page is null"); }
		//        if (string.IsNullOrEmpty(webPartUrl)) { throw new Exception("Url for webpart is null"); }
		//        if (string.IsNullOrEmpty(zoneId)) { zoneId = "Zone 1"; }
		//        string errorMessage = null;


		//        // get web parts
		//        using (SPLimitedWebPartManager webPartManager = GetWebPartManager(web, pageUrl))
		//        {
		//            // get xml reader of webpart
		//            System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(
		//                new System.IO.StringReader(web.GetFileAsString(webPartUrl)));
					
		//            // get webpart object
		//            webPart = webPartManager.ImportWebPart(reader, out errorMessage);
		//            if (webPart == null || !string.IsNullOrEmpty(errorMessage))
		//            { throw new Exception("Failed to reference webpart using url: " + webPartUrl + " with error: " + errorMessage); }

		//            // set id
		//            if (string.IsNullOrEmpty(webPart.ID)) { webPart.ID = CreateWebPartId(); }

		//            // turn off chrome
		//            webPart.ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.None;

		//            // add webpart to page
		//            webPartManager.AddWebPart(webPart, zoneId, 1);

		//            // save
		//            webPartManager.SaveChanges(webPart);
		//        }
		//    }
		//    catch (Exception ex)
		//    {
		//        Log.WriteError("drsyr7tjjedstrdxzzsd", ex, "url: " + pageUrl);
		//        webPart = null;
		//    }
		//    return webPart;
		//}

		/// <summary>
		/// Were webpart should be inserted into Rich Content or wiki
		/// </summary>
		public enum WebPartLocation
		{
			Beginning,
			End,
			ReplaceKeyword,
			None,
		}
		/// <summary>
		/// Unique string in rich content that will be replaced with webpart programamtically
		/// </summary>
		public const string WebPartLocationReplacementKeyword = "^";

		/// <summary>
		/// Generate a new webpartId in a specific format
		/// http://blog.mastykarz.nl/programmatically-adding-web-parts-rich-content-sharepoint-2010/
		/// </summary>
		/// <returns></returns>
		public static string CreateWebPartId(ref Guid guid)
		{
			guid = Guid.NewGuid();
			return String.Format("g_{0}", guid.ToString().Replace('-', '_'));
		}
		/// <summary>
		/// Generate a new webpartId in a specific format
		/// http://blog.mastykarz.nl/programmatically-adding-web-parts-rich-content-sharepoint-2010/
		/// </summary>
		/// <returns></returns>
		public static string CreateWebPartId()
		{
			Guid guid = Guid.NewGuid();
			return CreateWebPartId(ref guid);
		}
		/// <summary>
		/// Create webpartHtml to insert into a rich content area
		/// </summary>
		/// <param name="webPartId"></param>
		/// <returns></returns>
		public static string CreateWebPartHtml(Guid webPartId)
		{
			return string.Format("<div contenteditable='false' class='ms-rtestate-read ms-rte-wpbox'>"
				+ "<div class='ms-rtestate-notify  ms-rtestate-read {0}' id='div_{0}' unselectable='on'></div>"
				+ "<div unselectable='on' id='vid_{0}' style='display: none;'></div>" 
				+ "</div>", webPartId.ToString("D")); 
		}

		/// <summary>
		/// get Guid object from webpartId
		/// </summary>
		/// <param name="webPartId"></param>
		/// <returns></returns>
		public static Guid GetGuidFromWebPartId(string webPartId)
		{
			string originalWebPartId = webPartId;
			Guid guid = Guid.Empty;
			if (!string.IsNullOrEmpty(webPartId))
			{
				// strip out the "g_" prefix
				if (webPartId.Length > 2 && webPartId.Substring(0, 2) == "g_")
				{
					webPartId = webPartId.Substring(2);
				}
				
				// replace underscores with dashes
				webPartId = webPartId.Replace("_", "-").Trim();

				// try convert to GUID
				try { guid = new Guid(webPartId); }
				catch (Exception ex)
				{
					Log.WriteError("erge67erhed", ex, "original webpartId: " + originalWebPartId
						+ " formatted id: " + webPartId);
				}
			}
			return guid;
		}

		

		/// <summary>
		/// Add a new webpart
		/// IMPORTANT: You still need to save the item or PublishinPage that webPart is added to
		/// http://blog.mastykarz.nl/programmatically-adding-web-parts-rich-content-sharepoint-2010/
		/// </summary>
		/// <param name="page"></param>
		/// <param name="webPartUrl"></param>
		public static string AddWebPart(SPFile file, string webPartFilename,  int? zoneIndex, bool isTurnOffChrome)
		{
			string webPartHtml = null;
			try
			{
				// init
				if (file == null) { throw new Exception("SPFile passed is null"); }
				if (string.IsNullOrEmpty(webPartFilename)) { throw new Exception("WebPart filename passed is null"); }


				// get webPartManager
				using (SPLimitedWebPartManager webPartManager = GetWebPartManager(file))
				{
					// get webPart
					System.Web.UI.WebControls.WebParts.WebPart webPartToAdd = GetWebPart(webPartManager, webPartFilename, WebPartScope.Site);
					if (webPartToAdd == null) { throw new Exception("Failed to get webpart using filename: " + webPartFilename); }

					// add webpart to the hidden webparts zone
					if (zoneIndex == null) { zoneIndex = 0; }
					Guid guid = Guid.Empty;
					webPartToAdd.ID = CreateWebPartId(ref guid);
					if (isTurnOffChrome) { webPartToAdd.ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.None; }
					webPartManager.AddWebPart(webPartToAdd, "wpz", (int)zoneIndex);

					// create webPart html to be added to the page Rich Content
					webPartHtml = CreateWebPartHtml(guid);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("dxfyggcdfdtyrdrxxcxcfdxr54", ex, "webpartFilename: " + webPartFilename);
				webPartHtml = null;
			}
			return webPartHtml;
		}

		/// <summary>
		/// adds a XsltListViewWebPart of an existing list to passed web part wiki page/publishing page
		/// </summary>
		/// <param name="file"></param>
		/// <param name="listName"></param>
		/// <param name="zoneIndex"></param>
		/// <param name="isTurnOffChrome"></param>
		/// <returns></returns>
		public static string AddListWebPart(SPFile file, string listName, int? zoneIndex, bool isTurnOffChrome)
		{
			string webPartHtml = null;
			try
			{
				// init
				if (file == null) { throw new Exception("SPFile passed is null"); }
				if (string.IsNullOrEmpty(listName)) { throw new Exception("list name passed is null"); }


				// get webPartManager
				using (SPLimitedWebPartManager webPartManager = GetWebPartManager(file))
				{
					// get list webpart
					XsltListViewWebPart listWebPart = new XsltListViewWebPart();
					listWebPart.ListDisplayName = listName;
					if (isTurnOffChrome) { listWebPart.ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.None; }

					// add webpart to the hidden webparts zone
					if (zoneIndex == null) { zoneIndex = 0; }
					Guid guid = Guid.Empty;
					listWebPart.ID = CreateWebPartId(ref guid);
					webPartManager.AddWebPart(listWebPart, "wpz", (int)zoneIndex);

					// create webPart html to be added to the page Rich Content
					webPartHtml = CreateWebPartHtml(guid);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("tr67ufhgkljdsghioesriudk", ex, "listName: " + listName);
				webPartHtml = null;
			}
			return webPartHtml;
		}


		public static bool AddWebPart(PublishingPage page, string webPartFilename, int? zoneIndex,
			WebPartLocation webPartLocation, bool isTurnOffChrome, bool isSave)
		{
			bool isSuccess = false;
			try
			{
				// init
				if (page == null) { throw new Exception("PublishinPage passed is null"); }


				// get WebPartManager
				SPLimitedWebPartManager webPartManager = GetWebPartManager(page);

				// call original
				string webPartHtml = AddWebPart(page.ListItem.File, webPartFilename, zoneIndex, isTurnOffChrome);
				if (string.IsNullOrEmpty(webPartHtml)) { throw new Exception("Failed to add WebPart to page: " + page.Url); }

				// insert webPart html reference
				if (webPartLocation == WebPartLocation.Beginning)
				{
					page.ListItem["PublishingPageContent"] = webPartHtml + page.ListItem["PublishingPageContent"];
				}
				else if (webPartLocation == WebPartLocation.End)
				{
					page.ListItem["PublishingPageContent"] = page.ListItem["PublishingPageContent"] + webPartHtml;
				}
				else if (webPartLocation == WebPartLocation.ReplaceKeyword)
				{
					string keyword = WebPartLocationReplacementKeyword;
					if (!string.IsNullOrEmpty(keyword))
					{
						page.ListItem["PublishingPageContent"] = ((string)page.ListItem["PublishingPageContent"]).Replace(keyword, webPartHtml);
					}
				}
				else if (webPartLocation == WebPartLocation.None)
				{
					// do nothing, member will return webPart html which you then manually add to publishing page
				}
				else
				{
					throw new Exception("Unknown webpart location option: " + webPartLocation.ToString());
				}

				// assume success
				isSuccess = true;
			}
			catch (Exception ex)
			{
				string pageUrl = null; if (page != null) { pageUrl = page.Url; }
				Log.WriteError("se5y4eu8dstretduyyuyg", ex, "pageUrl: " + pageUrl);
				isSuccess = false;
			}
			return isSuccess;
		}



		/// <summary>
		/// Remove all webParts from passed page: wither PublishingPage or wiki page
		/// </summary>
		/// <param name="file"></param>
		public static void ClearAll(SPFile file)
		{
			try
			{
				// init
				if (file == null) { throw new Exception("SPFile passed is null"); }
				SPLimitedWebPartManager webPartManager = GetWebPartManager(file);
				if (webPartManager == null) { throw new Exception("Failed to get webPartManger"); }

				while (webPartManager.WebParts.Count > 0)
				{
					webPartManager.DeleteWebPart(webPartManager.WebParts[0]);
				}
			}
			catch (Exception ex)
			{
				string pageUrl = null; if (file != null) { pageUrl = file.Url; }
				Log.WriteError("rtsydetrjther457rt", ex, "url:" + pageUrl);
			}
		}

		
	}
}
